﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Modelo;
using PloobsEngine.SceneControl;
using PloobsEngine.Cameras;

namespace PloobsEngine.Material
{
    public class CustomDeferred : IShader
    {
        private string effect;
        private Effect _shader;
        private bool useGlow;
        private bool useParalax;
        private bool useBump;
        private bool useSpecular;

        public bool UseParalax
        {
            get { return useParalax; }
            set { useParalax = value; }
        }

        public bool UseGlow
        {
            get { return useGlow; }
            set { useGlow = value; }
        }
        

        public bool UseBump
        {
            get { return useBump; }
            set { useBump = value; }
        }        

        public bool UseSpecular
        {
            get { return useSpecular; }
            set { useSpecular = value; }
        }

        private float specularIntensity = 0;
        public float SpecularIntensity
        {
            get { return specularIntensity; }
            set { specularIntensity = value; }
        }
        private float specularPower = 0;

        public float SpecularPower
        {
            get { return specularPower; }
            set { specularPower = value; }
        }

        public override MaterialType MaterialType
        {
            get { return MaterialType.DEFERRED; }
        }

        public CustomDeferred(bool useGlow,bool useBump,bool useSpecular,bool useParalax)
        {
            this.effect = "AllBuffer";
            this.useGlow = useGlow;
            this.useSpecular = useSpecular;
            this.useBump = useBump;
            this.useParalax = useParalax;
            if (useParalax == true)
                useBump = true;
        }

        private Vector2 scaleBias = new Vector2(0.04f, -0.03f);

        /// <summary>
        /// Default  Vector2(0.04f, -0.03f);
        /// used for paralax
        /// </summary>
        public Vector2 ScaleBias
        {
            get { return scaleBias; }
            set { scaleBias = value; }
        }

        public override void Draw(IModelo modelo, IRenderHelper render, ICamera cam)
        {
            if (obj != null)
            {
                this._shader.Parameters["id"].SetValue(shaderId);
                this._shader.Parameters["useParalax"].SetValue(useParalax);
                this._shader.Parameters["useGlow"].SetValue(useGlow);
                this._shader.Parameters["useBump"].SetValue(useBump);
                this._shader.Parameters["useSpecular"].SetValue(useSpecular);            
                this._shader.Parameters["Texture"].SetValue(modelo.getTexture(TextureType.DIFFUSE));
                if (useBump)
                {
                    if (useParalax)
                    {
                        this._shader.Parameters["HeightMap"].SetValue(modelo.getTexture(TextureType.PARALAX));
                        this._shader.Parameters["scaleBias"].SetValue(scaleBias);                        
                    }

                    this._shader.Parameters["NormalMap"].SetValue(modelo.getTexture(TextureType.BUMP));

                }
                if (useSpecular)
                {
                    this._shader.Parameters["SpecularMap"].SetValue(modelo.getTexture(TextureType.SPECULAR));
                }
                else
                {
                    this._shader.Parameters["specularIntensity"].SetValue(specularIntensity);
                    this._shader.Parameters["specularPower"].SetValue(specularPower);
                }

                if (useGlow)
                    this._shader.Parameters["glow"].SetValue(modelo.getTexture(TextureType.GLOW));
                                        
               this._shader.Parameters["View"].SetValue(cam.View);
               this._shader.Parameters["Projection"].SetValue(cam.Projection);

                if(useParalax)
                    this._shader.Parameters["CameraPos"].SetValue(cam.Position);
                                
                Matrix[] boneTransforms = modelo.getBonesTransformation();
                Matrix wld = obj.getWorldMatrix();

                for (int i = 0; i < modelo.MeshNumber; i++)
                {
                    BatchInformation[] bi = modelo.GetBatchInformation(i);
                    Matrix w1 = Matrix.Multiply(wld, boneTransforms[modelo.GetParentBoneIndex(i)]);                    
                    this._shader.Parameters["World"].SetValue(w1);
                    this._shader.Parameters["WorldInverseTranspose"].SetValue(Matrix.Transpose(Matrix.Invert(w1))); 
                    for (int j = 0; j < bi.Count(); j++)
                    {

                        this._shader.Begin();
                        EngineStuff.GraphicsDevice.VertexDeclaration = bi[j].VertexDeclaration;
                        EngineStuff.GraphicsDevice.Vertices[0].SetSource(modelo.GetVertexBuffer(i), bi[j].StreamOffset, bi[j].VertexStride);
                        EngineStuff.GraphicsDevice.Indices = modelo.GetIndexBuffer(i);

                        this._shader.CurrentTechnique.Passes[0].Begin();
                        EngineStuff.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, bi[j].BaseVertex, 0, bi[j].NumVertices, bi[j].StartIndex, bi[j].PrimitiveCount);
                        this._shader.CurrentTechnique.Passes[0].End();
                        this._shader.End();
                    }

                }               
            }
        }
        public override void Initialize()
        {
            base.Initialize();
            this._shader = EngineStuff.InternalContentManager.GetAsset<Effect>(effect);            
            //this._shader = EngineStuff.CustomContentManager.GetAsset<Effect>("Effects\\AllBuffer");            
        }
    }
}
